#include "tcp_acceptor.h"

using namespace uvpp;

TCPAcceptor::TCPAcceptor(EventLoop* loop, bool noDelay)
	:_loop(loop),
	_noDelay(noDelay),
	_listened(false)
{
	::uv_tcp_init(loop->raw(), &_server);
	if (noDelay)
	{
		::uv_tcp_nodelay(&_server, 1);
	}
	_server.data = (void*)this;
}

TCPAcceptor::~TCPAcceptor()
{

}

int TCPAcceptor::bind(InetAddress& address)
{
	return ::uv_tcp_bind(&_server, address.addr(), 0);
}

int TCPAcceptor::listen()
{
	int ret = ::uv_listen((uv_stream_t*)&_server, 128,
		[](uv_stream_t* server, int status) 
		{
			if (status < 0)
			{
				// log
				return;
			}

			TCPAcceptor* acceptor = static_cast<TCPAcceptor*>(server->data);
			TCPPtr client = std::make_shared<uv_tcp_t>();
			::uv_tcp_init(acceptor->loop()->raw(), client.get());
			if (acceptor->isNoDelay())
			{
				::uv_tcp_nodelay(client.get(), 1);
			}

			if (::uv_accept(server, (uv_stream_t*)client.get()) == 0)
			{
				// new connection incoming.
				acceptor->onNewConnection(client);
			}
			else {
				// accept failed, close the client connection, and do the other things.
				::uv_close((uv_handle_t*)client.get(), nullptr);
			}
		});
		
	if (ret == 0)
	{
		_listened = true;
	}

	return ret;
}

EventLoop* TCPAcceptor::loop()
{
	return _loop;
}

bool TCPAcceptor::isNoDelay()
{
	return _noDelay;
}

void TCPAcceptor::onNewConnection(TCPPtr client)
{
	if (_newConnectionCallback != nullptr)
	{
		_newConnectionCallback(_loop, client);
	}
}

void TCPAcceptor::setNewConnectionCallback(NewConnectionCallback callback)
{
	_newConnectionCallback = callback;
}
